package com.depository.common.utils.validator;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
	 
	public class JsonValidator {
	 
	    private static CharacterIterator it;
	    private static char              c;
	    private static int               col;
	 
	    public JsonValidator(){
	    }
	 
	    /**
	     * 验证一个字符串是否是合法的JSON串
	     *
	     * @param input 要验证的字符串
	     * @return true-合法 ，false-非法
	     */
	    public static boolean validate(String input) {
	        input = input.trim();
	        boolean ret = valid(input);
	        return ret;
	    }
	 
	    private static boolean valid(String input) {
	        if ("".equals(input)) return true;
	 
	        boolean ret = true;
	        it = new StringCharacterIterator(input);
	        c = it.first();
	        col = 1;
	        if (!value()) {
	            ret = error("value", 1);
	        } else {
	            skipWhiteSpace();
	            if (c != CharacterIterator.DONE) {
	                ret = error("end", col);
	            }
	        }
	 
	        return ret;
	    }
	 
	    private static boolean value() {
	        return literal("true") || literal("false") || literal("null") || string() || number() || object() || array();
	    }
	 
	    private static boolean literal(String text) {
	        CharacterIterator ci = new StringCharacterIterator(text);
	        char t = ci.first();
	        if (c != t) return false;
	 
	        int start = col;
	        boolean ret = true;
	        for (t = ci.next(); t != CharacterIterator.DONE; t = ci.next()) {
	            if (t != nextCharacter()) {
	                ret = false;
	                break;
	            }
	        }
	        nextCharacter();
	        if (!ret) error("literal " + text, start);
	        return ret;
	    }
	 
	    private static boolean array() {
	        return aggregate('[', ']', false);
	    }
	 
	    private static boolean object() {
	        return aggregate('{', '}', true);
	    }
	 
	    private static boolean aggregate(char entryCharacter, char exitCharacter, boolean prefix) {
	        if (c != entryCharacter) return false;
	        nextCharacter();
	        skipWhiteSpace();
	        if (c == exitCharacter) {
	            nextCharacter();
	            return true;
	        }
	 
	        for (;;) {
	            if (prefix) {
	                int start = col;
	                if (!string()) return error("string", start);
	                skipWhiteSpace();
	                if (c != ':') return error("colon", col);
	                nextCharacter();
	                skipWhiteSpace();
	            }
	            if (value()) {
	                skipWhiteSpace();
	                if (c == ',') {
	                    nextCharacter();
	                } else if (c == exitCharacter) {
	                    break;
	                } else {
	                    return error("comma or " + exitCharacter, col);
	                }
	            } else {
	                return error("value", col);
	            }
	            skipWhiteSpace();
	        }
	 
	        nextCharacter();
	        return true;
	    }
	 
	    private static boolean number() {
	        if (!Character.isDigit(c) && c != '-') return false;
	        int start = col;
	        if (c == '-') nextCharacter();
	        if (c == '0') {
	            nextCharacter();
	        } else if (Character.isDigit(c)) {
	            while (Character.isDigit(c))
	                nextCharacter();
	        } else {
	            return error("number", start);
	        }
	        if (c == '.') {
	            nextCharacter();
	            if (Character.isDigit(c)) {
	                while (Character.isDigit(c))
	                    nextCharacter();
	            } else {
	                return error("number", start);
	            }
	        }
	        if (c == 'e' || c == 'E') {
	            nextCharacter();
	            if (c == '+' || c == '-') {
	                nextCharacter();
	            }
	            if (Character.isDigit(c)) {
	                while (Character.isDigit(c))
	                    nextCharacter();
	            } else {
	                return error("number", start);
	            }
	        }
	        return true;
	    }
	 
	    private static boolean string() {
	        if (c != '"') return false;
	 
	        int start = col;
	        boolean escaped = false;
	        for (nextCharacter(); c != CharacterIterator.DONE; nextCharacter()) {
	            if (!escaped && c == '\\') {
	                escaped = true;
	            } else if (escaped) {
	                if (!escape()) {
	                    return false;
	                }
	                escaped = false;
	            } else if (c == '"') {
	                nextCharacter();
	                return true;
	            }
	        }
	        return error("quoted string", start);
	    }
	 
	    private static boolean escape() {
	        int start = col - 1;
	        if (" \\\"/bfnrtu".indexOf(c) < 0) {
	            return error("escape sequence  \\\",\\\\,\\/,\\b,\\f,\\n,\\r,\\t  or  \\uxxxx ", start);
	        }
	        if (c == 'u') {
	            if (!ishex(nextCharacter()) || !ishex(nextCharacter()) || !ishex(nextCharacter())
	                || !ishex(nextCharacter())) {
	                return error("unicode escape sequence  \\uxxxx ", start);
	            }
	        }
	        return true;
	    }
	 
	    private static boolean ishex(char d) {
	        return "0123456789abcdefABCDEF".indexOf(c) >= 0;
	    }
	 
	    private static char nextCharacter() {
	        c = it.next();
	        ++col;
	        return c;
	    }
	 
	    private static void skipWhiteSpace() {
	        while (Character.isWhitespace(c)) {
	            nextCharacter();
	        }
	    }
	 
	    private static boolean error(String type, int col) {
	         System.out.printf("type: %s, col: %s%s", type, col, System.getProperty("line.separator"));
	        return false;
	    }
	    public static void main(String[] args){
	        String jsonStr = "{\"website\":\"oschina.net\"";
	        System.out.println(jsonStr);
	        System.out.println(new JsonValidator().validate(jsonStr));
	    }
	}
